#!/usr/bin/env python3
import argparse
import random
import socket
import sys

from scapy.all import (
    IP,
    TCP,
    UDP,
    Ether,
    Packet,
    bind_layers,
    get_if_hwaddr,
    get_if_list,
    sendp
)
from scapy.fields import *


def get_if():
    ifs=get_if_list()
    iface=None # "h1-eth0"
    for i in get_if_list():
        if "eth0" in i:
            iface=i
            break;
    if not iface:
        print("Cannot find eth0 interface")
        exit(1)
    return iface

class SourceRoute(Packet):
   fields_desc = [ BitField("bos", 0, 1),
                   BitField("port", 0, 15)]

bind_layers(Ether, SourceRoute, type=0x1234)
bind_layers(SourceRoute, SourceRoute, bos=0)
bind_layers(SourceRoute, IP, bos=1)

def main():
    print("ipv4 forwarding: ./send.py <target IP address> <message> --mode ip")
    print("source routing : ./send.py <target IP address> <message>")

    if len(sys.argv)<2:
        print('pass 2 arguments: <destination>')
        exit(1)

    parser = argparse.ArgumentParser()
    parser.add_argument('ip_addr', type=str, help="The destination IP address to use")
    parser.add_argument('message', type=str, help="The message to include in packet")
    parser.add_argument('--modes', type=str, default=None, help="The mode to choose IPv4 forwarding")
    args = parser.parse_args()

    addr = socket.gethostbyname(args.ip_addr)
    mode = args.modes
    iface = get_if()
    
    print("sending on interface %s to %s" % (iface, str(addr)))

    if (mode is not None): 
        if (mode == "ip"):
            pkt =  Ether(src=get_if_hwaddr(iface), dst='ff:ff:ff:ff:ff:ff')
            pkt = pkt /IP(dst=addr) / TCP(dport=1234, sport=random.randint(49152,65535)) / args.message
            pkt.show2()
            sendp(pkt, iface=iface, verbose=False)
        else:
            print("mode must be 'ip' or None")
            exit(1)
    else: 
        while True:
            print()
            s = str(input('Type space separated port nums '
                            '(example: "2 3 2 2 1") or "q" to quit: '))
            if s == "q":
                break;
            print()

            i = 0
            pkt =  Ether(src=get_if_hwaddr(iface), dst='ff:ff:ff:ff:ff:ff')
            for p in s.split(" "):
                try:
                    pkt = pkt / SourceRoute(bos=0, port=int(p))
                    i = i+1
                except ValueError:
                    pass
            if pkt.haslayer(SourceRoute):
                pkt.getlayer(SourceRoute, i).bos = 1

            pkt = pkt / IP(dst=addr) / UDP(dport=4321, sport=1234) / args.message
            pkt.show2()
            sendp(pkt, iface=iface, verbose=False)

        #pkt = pkt / SourceRoute(bos=0, port=2) / SourceRoute(bos=0, port=3);
        #pkt = pkt / SourceRoute(bos=0, port=2) / SourceRoute(bos=0, port=2);
        #pkt = pkt / SourceRoute(bos=1, port=1)

if __name__ == '__main__':
    main()
